#!/bin/bash
#set -x
WORK_PATH=$(readlink -f ${0} | xargs dirname)
script_name=$(basename $0)
source ${WORK_PATH}/.${script_name%\.*}.conf

lock_file="${WORK_PATH}/.${script_name%\.*}.lock"
log_dir="${WORK_PATH}/log/$(date +%Y%m%d%H)"
log="${log_dir}/${script_name%\.*}.log"

exec_command=$@
start_time_s=$(date +%s)
######################################################
# common function
######################################################
function usage
{
    echo "Usage: $(basename $0) command [test-unit]"
    echo "command:"
    echo "    help            Show list of command-line options"
    echo "    init-env        Initialize or upgrade the build and test environment."
    echo "    show-env        Display test environment info."
    echo "    reset-docker    Reset test docker container."
    echo "    restart-docker  Restart test docker container."
    echo "    update          Update source code from github."
    echo "    build           Build and install the source code into the docker."
    echo "    test            Execute test in the docker."
    echo "    build-test      Build and install the source code into the docker and then execute the test script in Docker."
    echo "    delete          Delete invalid source code from local."
    echo "    delete-log      Delete old logs."
    echo ""

    echo "test-unit:"
    echo "    all             all unit."
    for unit_name in ${!TEST_TARGET[@]}; do
        if [[ ${unit_name} != "" ]]; then
            echo "    ${unit_name}            ${unit_name} unit."
        fi
    done
}
function start_run
{
    if [[ -e ${lock_file} ]]; then
        echo -e "\e[31m[ERR ] Others are using the current environment.\e[m"
        exit 1
    else
        touch ${lock_file}
        if [[ -e ${log_dir} ]]; then
            rm -fr ${log_dir}/*
            :> ${log}
        else
            mkdir -p ${log_dir}
            :> ${log}
        fi

        find ${WORK_PATH}/log -type f -mtime +30 -exec rm -rf {} \;

        echo "#####################################################"  | tee -a ${log}
        echo "# Execute Command: ${exec_command}"                     | tee -a ${log}
        echo "# Start Time     : $(date +%Y/%m/%d-%H:%M:%S)"          | tee -a ${log}
        echo "#####################################################"  | tee -a ${log}
    fi
}
function normal_exit
{
    # delete lock file.
    if [[ -e ${lock_file} ]]; then
        rm -fr ${lock_file}
    fi
    local end_time_s=$(date +%s)
    echo "#####################################################"  | tee -a ${log}
    echo "# The execute command (${exec_command}) normal end."    | tee -a ${log}
    echo "# End Time       : $(date +%Y/%m/%d-%H:%M:%S)"          | tee -a ${log}
    echo "# Execution Time : $[ $end_time_s - $start_time_s ]s"   | tee -a ${log}
    echo "# The Log log storage path => ${log_dir}"               | tee -a ${log}
    echo "#####################################################"  | tee -a ${log}
    exit 0
}
function abnormal_exit
{
    # delete lock file.
    if [[ -e ${lock_file} ]]; then
        rm -fr ${lock_file}
    fi
    local end_time_s=$(date +%s)
    echo "#####################################################"
    echo "# The execute command (${exec_command}) abnormal end."
    echo "# Execution Time : $[ $end_time_s - $start_time_s ]s" 
    echo "# End Time       : $(date +%Y%m%d-%H:%M:%S)"           
    echo "#####################################################"
    exit 1
}

function output_current_env_info
{
    echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
    echo "[INFO] Start display the current environment info."
    local env_cfg_file=${WORK_PATH}/${ENV_PATH#*./}/${ENV_CFG_FILE#*./}
    if [[ -e ${env_cfg_file} ]]; then
        sed '1,3d;$d' ${env_cfg_file}
        if [[ $? -ne 0 ]]; then
            echo "[ERR] Failed to git display current environment info"
            abnormal_exit
        fi
    else
        echo "[ERR ] the current environment info file does not exists."
        abnormal_exit
    fi
    echo "[INFO] Successfully display current environment info"
    echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
    echo ""
}
function output_current_source_info
{
    echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
    echo "[INFO] Start display current source code info."
    local src_cfg_file=${WORK_PATH}/${SRC_PATH#*./}/${SRC_CFG_FILE#*./}
    if [[ -e ${src_cfg_file} ]]; then
        sed '1,3d;$d' ${src_cfg_file}
        if [[ $? -ne 0 ]]; then
            echo "[ERR] Failed to git display current source code info"
            abnormal_exit
        fi
    else
        echo "[ERR ] The current source code info file does not exists."
        abnormal_exit
    fi

    echo "[INFO] Successfully display the current source code info."
    echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
    echo ""
}
function show_env_info
{
    local env_cfg_file=${WORK_PATH}/${ENV_PATH#*./}/${ENV_CFG_FILE#*./}
    if [[ -e ${env_cfg_file} ]]; then
        sed '1,3d;$d' ${env_cfg_file}
        if [[ $? -ne 0 ]]; then
            echo "[ERR] Failed to git display current environment info"
            abnormal_exit
        fi
    else
        echo "[ERR ] the current environment info file does not exists."
        abnormal_exit
    fi
}

######################################################
# delete old logs.
######################################################
function delete_old_log
{
    local day_count=5
    echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
    echo "[INFO] Start delete log from ${day_count} day ago."
    local old_date=$(date --date="${day_count} day ago" +%Y%m%d%H%M)
    cd ${WORK_PATH}/log
    # find ${WORK_PATH}/log/ -type d -mtime +${day_count} -exec rm -Rf {} \;
    for dir_name in $(ls); do
        if [[ ${dir_name} < ${old_date} ]]; then
            rm -fr ${dir_name}
            if [[ $?  -ne 0 ]]; then
                echo "[ERR ] Failed to delete log from ${day_count} day ago."
                echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
                abnormal_exit
            else
                echo "[INFO] delete directory name ${dir_name}"
            fi
        fi
    done
    echo "[INFO] Successfully delete log from ${day_count} day ago."
    echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
    echo ""
    cd ${WORK_PATH}
}

######################################################
# git option.
######################################################
function get_git_branch
{
    local repo_path="$1"
    cd ${repo_path}
    echo $(git rev-parse --abbrev-ref HEAD)
    cd - >/dev/null
}
function get_git_version
{
    local repo_path="$1"
    cd ${repo_path}
    echo $(git rev-parse HEAD)
    cd - >/dev/null
}
function git_clone_update
{
    local git_repo_url=$1
    local git_repo=$2
    local git_branch=$3
    local git_commitid=$4
    echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
    echo "[INFO] Start update ${git_repo} from github."
    if [[ ${git_repo_url} != "" ]] && [[ ${git_repo} != "" ]] && [[ ${git_branch} != "" ]]; then
        if [[ -e ${git_repo} ]] && [[ -e ${git_repo}/.git ]] ;then
            cd ${git_repo}
            # reset branch
            git reset --hard HEAD
            git clean -df
            # switch master branch
            if [[ $(git rev-parse --abbrev-ref HEAD) != "master" ]]; then
                git switch master
            fi
            # delete other local branch
            local other_branches=$(git branch -l |grep -v master)
            if [[ ${other_branches} != "" ]]; then 
                git branch -D ${other_branches}
            fi
            # sync remote branch name
            git remote prune origin
            # update all branch
            echo "[INFO] Exec command=>$ git pull"
            git pull
            if [[ $? -ne 0 ]]; then
                echo "[ERR ] Failed to git pull branch."
                abnormal_exit
            fi
        else
            # clone repository
            rm -fr ${git_repo}
            echo "[INFO] Exec command=>$ git clone --progress ${git_repo_url} 2>${WORK_PATH}/${ENV_PATH#*./}/.git_progress.log"
            git clone --progress ${git_repo_url} 2>${WORK_PATH}/${ENV_PATH#*./}/.git_progress.log
            if [[ $? -ne 0 ]]; then
                echo "[ERR ] Failed to git clone repo. repo_url=>${repo_url}"
                abnormal_exit
            fi
            cd ${git_repo}
        fi
        # switch branche
        if [[ $(git rev-parse --abbrev-ref HEAD) != "${git_branch}" ]]; then
            echo "[INFO] Exec command=>$ git switch ${git_branch}"
            git switch ${git_branch}
            if [[ $? -ne 0 ]]; then
                echo "[ERR ] Failed to git switch branch. branch=>${git_branch}"
                abnormal_exit
            fi
        fi
        # reset commit id
        if [[ ${git_commitid} != "" ]];then
            echo "[INFO] Exec command=>$ git reset --hard ${git_commitid}"
            git reset --hard ${git_commitid}
            if [[ $? -ne 0 ]]; then
                echo "[ERR ] Failed to git reset --hard ${git_commitid}"
                abnormal_exit
            fi
        fi
        cd - >/dev/null
    fi
    echo "[INFO] Successfully update ${git_repo} from github."
    echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
    echo ""
}


######################################################
# Initialize the build and test environment.
######################################################
function install_build_docker
{
    echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
    echo "[INFO] Start install build docker."
    local env_path=${WORK_PATH}/${ENV_PATH#*./}
    local env_cfg_file=${env_path}/${ENV_CFG_FILE#*./}
    local docker_git_cfg=(${GIT_ENV_REPO[build_docker]//:/ })
    local git_repo=${docker_git_cfg[1]}
    local git_branch=${docker_git_cfg[2]}
    local script_command=${docker_git_cfg[3]}
    local git_repo_url=${GIT_ENV_URL}/${docker_git_cfg[0]}/${git_repo}

    # Download and update docker config code.
    cd ${env_path}
    git_clone_update ${git_repo_url} ${git_repo} ${git_branch}

    # modify config file
    cd ${git_repo}
    sed -ri '1,3s/ubuntu-18.04/ubuntu-20.04/g' ./Dockerfile
    sed -ri 's/(^\s+python-git \\$)/#\1/g' ./Dockerfile

    # install build docker
    local docker_image_name="${BUILD_DOCKER_REPOSITORY}"
    local docker_image_tag="${BUILD_DOCKER_TAG}"
    local curr_build_docker_image_id=$(docker images ${docker_image_name}:${docker_image_tag} --format "{{.ID}}")
    if [[ ${curr_build_docker_image_id} != "" ]]; then
        echo "[INFO] The target docker already exists. ID=>${curr_build_docker_image_id}"
    else
        echo "[INFO] The target docker installing ..."
        docker build --build-arg http_proxy=${http_proxy} --build-arg https_proxy=${https_proxy} -t ${docker_image_name}:${docker_image_tag} .
        if [[ $?  -ne 0 ]]; then
            echo "[ERR ] # Failed to install build docker. image=>${docker_image_name}:${docker_image_tag}"
            abnormal_exit
        fi
        curr_build_docker_image_id=$(docker images ${docker_image_name}:${docker_image_tag} --format "{{.ID}}")

        # check install status
        if [[ ${curr_build_docker_image_id} == "" ]]; then
            echo "[ERR ] # Failed to install build docker. image[${docker_image_name}:${docker_image_tag}] does not exist."
            abnormal_exit
        fi

    fi

    # save install info to file
    echo "Build docker info:"                                     >> ${env_cfg_file}
    echo "    REPOSITORY: ${docker_image_name}"                   >> ${env_cfg_file}
    echo "    TAG: ${docker_image_tag}"                           >> ${env_cfg_file}
    echo "------------------------------------------------------" >> ${env_cfg_file}
    echo ""                                                       >> ${env_cfg_file}

    cd ${WORK_PATH}
    echo "[INFO] Successfully install build docker."
    echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
    echo ""
}
function install_build_sdk
{
    echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
    echo "[INFO] Start install sdk."
    local env_path=${WORK_PATH}/${ENV_PATH#*./}
    local env_cfg_file=${env_path}/${ENV_CFG_FILE#*./}
    local sdk_install_file=${WGET_SDK_URL##*/}
    local sdk_version=$(echo ${WGET_SDK_URL} | grep -Eo "[0-9]{8}_SDK_v[0-9]+\.[0-9]+\.[0-9]+\.[A-Z]")
    # strip : echo " a bc " | awk '$1=$1'
    local curr_sdk_version=$(sed -n '1p' ${WORK_PATH}/${ENV_PATH#*./}/.wget_sdk_progress.log | grep -Eo "[0-9]{8}_SDK_v[0-9]+\.[0-9]+\.[0-9]+\.[A-Z]")

    cd ${env_path}
    if [[ "${curr_sdk_version}" == "${sdk_version}" ]]; then
        echo "[INFO] The sdk does not need to be upgraded."
    else
        echo "[INFO] The sdk start to upgrade."
        # delete old sdk
        rm -fr arene-toolchain-cockpit-ivi-*
        rm -fr sdk

        # download new sdk
        echo "[INFO] Exec command=>$ wget ${WGET_SDK_URL} 2>${WORK_PATH}/${ENV_PATH#*./}/.wget_sdk_progress.log"
        wget ${WGET_SDK_URL} 2>${WORK_PATH}/${ENV_PATH#*./}/.wget_sdk_progress.log
        if [[ $?  -ne 0 ]]; then
            echo "[ERR ] # Failed to download new sdk. WGET_SDK_URL=>${WGET_SDK_URL}"
            abnormal_exit
        fi

        # install new sdk
        cd ${WORK_PATH}
        docker run --rm -it -v ~:/home/hosthome:ro -v $(pwd):/workdir --name poky-$(id -un)-arene_integ --workdir=/workdir ${BUILD_DOCKER_REPOSITORY}:${BUILD_DOCKER_TAG} \
            bash -c "bash ./${ENV_PATH#*./}/${sdk_install_file} -y -d ./${ENV_PATH#*./}/sdk; exit"
        if [[ $?  -ne 0 ]]; then
            echo "[ERR ] # Failed to install new sdk. SDK_INSTALL_FILE=>${sdk_install_file}"
            abnormal_exit
        fi

        echo "[INFO] The sdk upgrade complete."
    fi

    # save install info to file
    echo "Build SDK info:"                                                                              >> ${env_cfg_file}
    echo "    SDK      Version: ${sdk_version}"                                                         >> ${env_cfg_file}
    echo "    SDK install file: ${sdk_install_file}"                                                    >> ${env_cfg_file}
    echo "    SDK load command: source ./${ENV_PATH#*./}/sdk/environment-setup-core2-64-arene-linux"    >> ${env_cfg_file}
    echo "------------------------------------------------------"                                       >> ${env_cfg_file}
    echo ""                                                                                             >> ${env_cfg_file}

    cd ${WORK_PATH}
    echo "[INFO] Successfully install sdk."
    echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
    echo ""
}
function install_test_docker
{
    echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
    echo "[INFO] Start install test docker."
    local env_path=${WORK_PATH}/${ENV_PATH#*./}
    local env_cfg_file=${env_path}/${ENV_CFG_FILE#*./}
    local docker_git_cfg=(${GIT_ENV_REPO[test_docker]//:/ })
    local git_repo=${docker_git_cfg[1]}
    local git_branch=${docker_git_cfg[2]}
    local script_command=${docker_git_cfg[3]}
    local git_repo_url=${GIT_ENV_URL}/${docker_git_cfg[0]}/${git_repo}

    # Download and update test docker config code.
    cd ${env_path}
    git_clone_update ${git_repo_url} ${git_repo} ${git_branch}

    # modify config
    cd ${git_repo}
    sed -ri 's/(^\s+setup$)/#\1/g' ./arene-ivi_docker.sh
    sed -ri 's/(^\s+xhost \+$)/#\1/g' ./arene-common_docker.sh
    sed -ri 's/(^DOCKER_IMAGE_HAL_NAME=sdk-docker-hal$)/\1-mock/g' ./sdk-hal-docker/.env
    sed -ri "s@WORK_DIR=~/hmifw_share@WORK_DIR=${WORK_PATH}@g" ./sdk-hal-docker/.env

    # Upgrade test docker.
    local cfg_docker_registry=$(grep DOCKER_REGISTRY ./sdk-hal-docker/.env | cut -d = -f 2)
    local cfg_docker_image_runtime_name=$(grep DOCKER_IMAGE_RUNTIME_NAME ./sdk-hal-docker/.env | cut -d = -f 2)
    local cfg_docker_image_runtime_tag=$(grep DOCKER_IMAGE_RUNTIME_TAG ./sdk-hal-docker/.env | cut -d = -f 2)
    local cfg_docker_image_hal_name=$(grep DOCKER_IMAGE_HAL_NAME ./sdk-hal-docker/.env | cut -d = -f 2)
    local cfg_docker_image_hal_tag=$(grep DOCKER_IMAGE_HAL_TAG ./sdk-hal-docker/.env | cut -d = -f 2)
    local curr_docker_image_runtime_tag=$(docker images  */${cfg_docker_image_runtime_name} --format "{{.Tag}}")
    local curr_docker_image_hal_tag=$(docker images  */${cfg_docker_image_hal_name} --format "{{.Tag}}")

    if [[ ${cfg_docker_image_hal_tag} != ${curr_docker_image_hal_tag} ]] || [[ ${cfg_docker_image_runtime_tag} != ${curr_docker_image_hal_tag} ]]; then
        echo "[INFO] The test docker start to upgrade."
        local  curr_container_runtime_id=$(docker ps -f ancestor=${cfg_docker_registry}/${cfg_docker_image_runtime_name}:${curr_docker_image_runtime_tag} --format "{{.ID}}")
        local  curr_container_hal_id=$(docker ps -f ancestor=${cfg_docker_registry}/${cfg_docker_image_hal_name}:${curr_docker_image_hal_tag} --format "{{.ID}}")

        # Stop and delete old test runtime docker container
        if [[ "" != ${curr_container_runtime_id} ]]; then
            # stop old test docker container
            docker stop ${curr_container_runtime_id}
            if [[ $?  -ne 0 ]]; then
                echo "[ERR ] Failed to stop runtime docker container.ID=>${curr_container_runtime_id}"
                abnormal_exit
            fi

            # delete old test docker container
            docker rm -f ${curr_container_runtime_id}
            if [[ $?  -ne 0 ]]; then
                echo "[ERR ] Failed to delete docker container.ID=>${curr_container_runtime_id}"
                abnormal_exit
            fi
        fi

        # Stop and delete old test hal docker container
        if [[ "" != ${curr_container_hal_id} ]]; then
            # stop old test docker container
            docker stop ${curr_container_hal_id}
            if [[ $?  -ne 0 ]]; then
                echo "[ERR ] Failed to stop runtime docker container.ID=>${curr_container_hal_id}"
                abnormal_exit
            fi

            # delete old test docker container
            docker rm -f ${curr_container_hal_id}
            if [[ $?  -ne 0 ]]; then
                echo "[ERR ] Failed to delete docker container.ID=>${curr_container_hal_id}"
                abnormal_exit
            fi
        fi

        # Delete old test runtime and hal docker images
        local curr_image_runtime_id=$(docker images ${cfg_docker_registry}/${cfg_docker_image_runtime_name}:${curr_docker_image_runtime_tag} --format "{{.ID}}")
        local curr_image_hal_id=$(docker images ${cfg_docker_registry}/${cfg_docker_image_hal_name}:${curr_docker_image_hal_tag} --format "{{.ID}}")
        # delete old test runtime docker image
        if [[ ${curr_image_runtime_id} != "" ]]; then
            docker rmi -f  ${curr_image_runtime_id}
            if [[ $?  -ne 0 ]]; then
                echo "[ERR ] # Failed to docker image.ID=>${curr_image_runtime_id}"
                abnormal_exit
            fi
        fi
        # delete old test hal docker image
        if [[ ${curr_image_hal_id} != "" ]]; then
            docker rmi -f  ${curr_image_hal_id}
            if [[ $?  -ne 0 ]]; then
                echo "[ERR ] # Failed to docker image.ID=>${curr_image_hal_id}"
                abnormal_exit
            fi
        fi

        # delete old docker image file
        rm -fr ./sdk-hal-docker/*.tar.gz
        sleep 2
        # install test docker image and start container
        export DISPLAY=:0.0
        ./${script_command} install
        # if [[ $?  -ne 0 ]]; then
        #     echo "[ERR ] Failed to install test docker image and container."
        #     abnormal_exit
        # fi
        echo "[INFO] The test docker upgrade complete."
    else
        echo "[INFO] The test docker does not need to be upgraded."
    fi


    # save install info to file
    local  curr_container_runtime_name=$(docker ps -f ancestor=${cfg_docker_registry}/${cfg_docker_image_runtime_name}:${cfg_docker_image_runtime_tag} --format "{{.Names}}")
    local  curr_container_hal_name=$(docker ps -f ancestor=${cfg_docker_registry}/${cfg_docker_image_hal_name}:${cfg_docker_image_hal_tag} --format "{{.Names}}")
    if [[ ${curr_container_runtime_name} == "" ]] || [[ ${curr_container_hal_name} == "" ]];then
        restart_test_docker_container
    fi
    echo "Test docker info:"                                                                                              >> ${env_cfg_file}
    echo "    runtime image: ${cfg_docker_registry}/${cfg_docker_image_runtime_name}:${cfg_docker_image_runtime_tag}"     >> ${env_cfg_file}
    echo "    runtime  name: ${curr_container_runtime_name}"                                                              >> ${env_cfg_file}
    echo ""                                                                                                               >> ${env_cfg_file}
    echo "    hal     image: ${cfg_docker_registry}/${cfg_docker_image_hal_name}:${cfg_docker_image_hal_tag}"             >> ${env_cfg_file}
    echo "    hal      name: ${curr_container_hal_name}"                                                                  >> ${env_cfg_file}
    echo "------------------------------------------------------"                                                         >> ${env_cfg_file}
    echo ""                                                                                                               >> ${env_cfg_file}

    cd ${WORK_PATH}
    echo "[INFO] Successfully install test docker."
    echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
    echo ""
}
function restart_test_docker_container
{
    echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
    echo "[INFO] Restart docker container."
    local env_path=${WORK_PATH}/${ENV_PATH#*./}
    local docker_git_cfg=(${GIT_ENV_REPO[test_docker]//:/ })
    local git_repo=${docker_git_cfg[1]}
    local script_command=${env_path}/${git_repo}/${docker_git_cfg[3]}
    export DISPLAY=:0.0
    (${script_command} restart 2>&1)
    if [[ $? -ne 0 ]]; then
        echo "[ERR ] Failed to restart docker container."
        abnormal_exit
    fi
    echo "[INFO] Successfully restart docker container."
    sleep 5
    echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
    echo ""
}
function stop_test_docker_container
{
    echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
    echo "[INFO] Delete docker container."
    local env_cfg_file=${ENV_PATH}/${ENV_CFG_FILE#*./}
    local runtime_docker_image=$(sed -n '5p' ${env_cfg_file} | cut -d : -f 2,3)
    local hal_docker_image=$(sed -n '8p' ${env_cfg_file} | cut -d : -f 2,3)
    local curr_container_runtime_id=$(docker ps -f "ancestor=${runtime_docker_image}" --format "{{.ID}}")
    local curr_container_hal_id=$(docker ps -f "ancestor=${hal_docker_image}" --format "{{.ID}}")
    # Stop and delete old test runtime docker container
    if [[ "" != ${curr_container_runtime_id} ]]; then
        # stop old test docker container
        docker stop ${curr_container_runtime_id}
        if [[ $?  -ne 0 ]]; then
            echo "[ERR ] Failed to stop runtime docker container.ID=>${curr_container_runtime_id}"
            abnormal_exit
        fi
        echo "[Info ] Failed to stop runtime docker container.ID=>${curr_container_runtime_id}"
        # delete old test docker container
        docker rm -f ${curr_container_runtime_id}
        if [[ $?  -ne 0 ]]; then
            echo "[ERR ] Failed to delete docker container.ID=>${curr_container_runtime_id}"
            abnormal_exit
        fi
    fi

    # Stop and delete old test hal docker container
    if [[ "" != ${curr_container_hal_id} ]]; then
        # stop old test docker container
        docker stop ${curr_container_hal_id}
        if [[ $?  -ne 0 ]]; then
            echo "[ERR ] Failed to stop runtime docker container.ID=>${curr_container_hal_id}"
            abnormal_exit
        fi
        echo "[Info ] Failed to stop runtime docker container.ID=>${curr_container_hal_id}"
        # delete old test docker container
        docker rm -f ${curr_container_hal_id}
        if [[ $?  -ne 0 ]]; then
            echo "[ERR ] Failed to delete docker container.ID=>${curr_container_hal_id}"
            abnormal_exit
        fi
    fi
    echo "[INFO] Successfully delete docker container."
    echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
    echo ""
}
function init_build_and_test_env
{
    echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
    echo "[INFO] Start initialize the build and test environment."
    local env_path=${WORK_PATH}/${ENV_PATH#*./}
    local env_cfg_file=${env_path}/${ENV_CFG_FILE#*./}
    if [[ ! -e ${env_path} ]]; then
        mkdir -p ${env_path}
    fi

    # save install info
    echo "######################################################" >  ${env_cfg_file}
    echo "# Then current environment info."                       >> ${env_cfg_file}
    echo "######################################################" >> ${env_cfg_file}

    # install test docker
    install_test_docker

    # install build docker
    install_build_docker

    # install build sdk
    install_build_sdk


    # output current environment info
    output_current_env_info

    echo "[INFO] Successfully initialize the build and test environment."
    echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
    echo ""
}

######################################################
# Update source code from github.
######################################################
function update_source_code
{
    echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
    echo "[INFO] Start update source code from github."
    local src_path=${WORK_PATH}/${SRC_PATH#*./}
    if [[ ! -e ${src_path} ]]; then
        mkdir -p ${src_path}
    fi
    cd ${src_path}
    for git_repo_cfg in ${GIT_SRC_REPO[@]}; do
        local tmp_array=(${git_repo_cfg//:/ })
        local git_group=${tmp_array[0]}
        local git_repo=${tmp_array[1]}
        local git_branch=${tmp_array[2]}
        local git_commitid=${tmp_array[3]}

        # git clone or update source code
        git_clone_update "${GIT_SRC_URL}/${git_group}/${git_repo}" ${git_repo} ${git_branch} ${git_commitid}
    done
    cd ${WORK_PATH}
    echo "[INFO] Successfully update source code from github."
    echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
    echo ""
}
######################################################
# Delete invalid source code from local.
######################################################
function delete_invalid_source
{
    echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
    echo "[INFO] Start delete invalid source code from local."
    if [[ -e ${SRC_PATH} ]]; then
        cd ${SRC_PATH}
        for dir_name in $(ls); do
            if [[ -e ./${dir_name}/.git ]] && [[ ! "${GIT_SRC_REPO[@]}" =~ "${dir_name}" ]]; then
                rm -fr ${dir_name}
            fi
        done
        cd ${WORK_PATH}
    fi
    echo "[INFO] Successfully delete invalid source code from local."
    echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
    echo ""
}


######################################################
# Build and install the source code into the docker.
######################################################
function build_source_code_to_sdk
{
    echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
    echo "[INFO] Start build and install source code to test docker."
    local build_sdk="./${ENV_PATH#*./}/sdk/environment-setup-core2-64-arene-linux"
    local build_path="./${SRC_PATH#*./}"

    local env_cfg_file=${ENV_PATH}/${ENV_CFG_FILE#*./}
    # local runtime_docker_name=$(sed -n '6p' ${env_cfg_file} | cut -d : -f 2)
    # local hal_docker_name=$(sed -n '9p' ${env_cfg_file} | cut -d : -f 2)
    
    local runtime_docker_name="sdk-hal-docker_arene_1"
    local hal_docker_name="sdk-hal-docker_app_1"

    local src_cfg_file=${SRC_PATH}/${SRC_CFG_FILE#*./}

    local build_install_path_tmp=$(grep SDKTARGETSYSROOT= ${build_sdk} | sed 's/export SDKTARGETSYSROOT=//g')

    echo "######################################################"   >  ${src_cfg_file}
    echo "# Then current source code info."                         >> ${src_cfg_file}
    echo "######################################################"   >> ${src_cfg_file}
    if [[ ! -e "./${BUILD_INSTALL_PATH#*./}" ]]; then
        mkdir -p "./${BUILD_INSTALL_PATH#*./}"
    else
        rm -fr "./${BUILD_INSTALL_PATH#*./}"
        mkdir -p "./${BUILD_INSTALL_PATH#*./}"
    fi

    #######################################################################
    # update arene-cockpit-api capnp to sdk
    #######################################################################
    rm -f ./${ENV_PATH#*./}/sdk/sysroots/core2-64-arene-linux/opt/arene/include/driver_assistance/DriverAssistanceCockpitAPI.capnp
    rm -f ./${ENV_PATH#*./}/sdk/sysroots/core2-64-arene-linux/opt/arene/include/diag/DiagCockpitAPI.capnp
    rm -f ./${ENV_PATH#*./}/sdk/sysroots/core2-64-arene-linux/opt/arene/include/ic/IcCockpitAPI.capnp
    rm -f ./${ENV_PATH#*./}/sdk/sysroots/core2-64-arene-linux/opt/arene/include/settings_provider/SettingsProviderCockpitAPI.capnp
    cp ./src/arene-cockpit-api/driver_assistance/DriverAssistanceCockpitAPI.capnp ./${ENV_PATH#*./}/sdk/sysroots/core2-64-arene-linux/opt/arene/include/driver_assistance/
    cp ./src/arene-cockpit-api/diag/DiagCockpitAPI.capnp ./${ENV_PATH#*./}/sdk/sysroots/core2-64-arene-linux/opt/arene/include/diag/
    cp ./src/arene-cockpit-api/ic/IcCockpitAPI.capnp ./${ENV_PATH#*./}/sdk/sysroots/core2-64-arene-linux/opt/arene/include/ic/
    cp ./src/arene-cockpit-api/settings_provider/SettingsProviderCockpitAPI.capnp ./${ENV_PATH#*./}/sdk/sysroots/core2-64-arene-linux/opt/arene/include/settings_provider/


    #######################################################################
    # build and install souce code to sdk
    #######################################################################
    echo "[INFO] Start build and install the source code ."
    build_install_log="${log_dir}/Readme_update_sdk_build.log"
    : > ${build_install_log}
    echo "-----------------------------------------------------"        >> ${build_install_log}
    echo "Start build and install the vehicle_cooperation and settingsprovider code ."  >> ${build_install_log}
    echo "-----------------------------------------------------"        >> ${build_install_log}
    docker run --rm -it -v ~:/home/hosthome:ro -v $(pwd):/workdir --name poky-$(id -un)-arene_integ --workdir=/workdir ${BUILD_DOCKER_REPOSITORY}:${BUILD_DOCKER_TAG} \
        bash -c "source /workdir/${build_sdk#*./} ;\
                cd /workdir/src/vehicle_cooperation/customize ;\
                make clean ;\
                make ;\
                make install ;\
                cd /workdir/src/vehicle_cooperation/diag ;\
                make clean ;\
                make ;\
                make install ;\
                cd /workdir/src/vehicle_cooperation/dms ;\
                make clean ;\
                make ;\
                make install ;\
                cd /workdir/src/vehicle_cooperation/driver_assistance ;\
                make clean ;\
                make ;\
                make install ;\
                cd /workdir/src/vehicle_cooperation/meter ;\
                make clean ;\
                make ;\
                make install ;\
                cd /workdir/src/vehicle_cooperation/timercharge ;\
                make clean ;\
                make ;\
                make install ;\
                cd /workdir/src/vehicle_cooperation/energy_monitor ;\
                make clean ;\
                make ;\
                make install ;\
                cd /workdir/src/arene-ivi-appsvc-settingsprovider ;\
                mkdir build ;\
                cd build ;\
                cmake .. ;\
                make -j 4 ;\
                make install DESTDIR=/workdir/env/sdk/sysroots/core2-64-arene-linux;\
                rm -rf build ;" >> ${build_install_log}  2>&1

    if [[ $?  -ne 0 ]]; then
        echo "[ERROR] Failed to build and install the sdk code of the vehicle_cooperation and settingsprovider !!!."
        exit 1
    fi
    echo "[INFO] Successfully build and install the sdk code of the vehicle_cooperation and settingsprovider."
    echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
    echo ""
}

######################################################
# Build and install the source code into the docker.
######################################################
function build_install_source_code
{
    echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
    echo "[INFO] Start build and install source code to test docker."
    local build_sdk="./${ENV_PATH#*./}/sdk/environment-setup-core2-64-arene-linux"

    local env_cfg_file=${ENV_PATH}/${ENV_CFG_FILE#*./}
    # local runtime_docker_name=$(sed -n '6p' ${env_cfg_file} | cut -d : -f 2)
    # local hal_docker_name=$(sed -n '9p' ${env_cfg_file} | cut -d : -f 2)
    
    local runtime_docker_name="sdk-hal-docker_arene_1"
    local hal_docker_name="sdk-hal-docker_app_1"

    local src_cfg_file=${SRC_PATH}/${SRC_CFG_FILE#*./}

    local build_install_path_tmp=$(grep SDKTARGETSYSROOT= ${build_sdk} | sed 's/export SDKTARGETSYSROOT=//g')

    echo "######################################################"   >  ${src_cfg_file}
    echo "# Then current source code info."                         >> ${src_cfg_file}
    echo "######################################################"   >> ${src_cfg_file}
    if [[ ! -e "./${BUILD_INSTALL_PATH#*./}" ]]; then
        mkdir -p "./${BUILD_INSTALL_PATH#*./}"
    else
        rm -fr "./${BUILD_INSTALL_PATH#*./}"
        mkdir -p "./${BUILD_INSTALL_PATH#*./}"
    fi


    # start build and install
    for build_target_cfg in ${BUILD_INSTALL_TARGET[@]}; do
        local tmp_array=(${build_target_cfg//:/ })
        local build_tool=${tmp_array[0]}
        local build_repo=${tmp_array[1]}
        local build_unit=$(echo ${tmp_array[2]} | sed 's@/@_@g')
        local has_hal=${tmp_array[3]}
        local cpu_num="$(cat /proc/cpuinfo | grep processor | wc -l)"

        local build_path="./${SRC_PATH#*./}"
        local build_install_path="./${BUILD_INSTALL_PATH#*./}"
        local log_file_prefix=${log_dir}
        # setting log and build and install path
        if [[ ${build_unit} == "all" ]]; then
            build_path=${build_path}/${build_repo}
            if [[ ! -e ${build_path} ]]; then
                echo "[ERR ] The repo does not exists.repo path=>${build_path}"
                abnormal_exit
            fi
            build_install_path="${build_install_path}/${build_repo}"
            log_file_prefix="${log_file_prefix}/${build_repo}"
        else
            build_path="${build_path}/${build_repo}/${tmp_array[2]}"
            if [[ ! -e ${build_path} ]]; then
                echo "[ERR ] The unit of then repo does not exists. unit path=>${build_path}"
                abnormal_exit
            fi
            build_install_path=${build_install_path}/${build_repo}/${build_unit}
            log_file_prefix="${log_file_prefix}/${build_repo}_${build_unit}"
        fi

        # build and install source code.
        local build_install_log=""
        local build_install_pkg_info=""
        echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ${build_repo}"
        echo "[INFO] Start build and installing source code using ${build_tool}."
        if [[ ${build_tool} == "cmake" ]]; then
            build_path="${build_path}/tmp_build"
            rm -fr ${build_path}
            mkdir -p ${build_path}
            if [[ ${has_hal} == "true" ]]; then
                #######################################################################
                # build and install maock
                #######################################################################
                # echo ${hal_docker_name}
                echo "[INFO] Build and install the mock code of the ${build_repo}."
                build_install_log="${log_file_prefix}_mock_build.log"
                : > ${build_install_log}
                echo "-----------------------------------------------------"        >> ${build_install_log}
                echo "Start build and install the mock code of the ${build_repo}."  >> ${build_install_log}
                echo "-----------------------------------------------------"        >> ${build_install_log}
                docker exec -it ${hal_docker_name}  bash -c "cd /home/user/work/${build_path#*./} ; \
                                                echo '$ cmake -DCMAKE_DOCKER_TYPE=Hal ${BUILD_OPTION} ..' ; \
                                                cmake  -DCMAKE_DOCKER_TYPE=Hal ${BUILD_OPTION} ..  ; \
                                                echo '$ make -j ${cpu_num}' ; \
                                                make -j ${cpu_num} 2>&1 | tee ; \
                                                make install 2>&1 | tee ; \
                                                make package 2>&1 | tee ; \
                                                chown -R 1002:1002 * ;\
                                                exit 0" >> ${build_install_log}  2>&1
                if [[ $(grep -Eo "make: \*\*\* [Makefile:[0-9]+: all] Error [0-9]+" ${build_install_log}) != "" ]]; then
                    echo "[WARN] Failed to build and install the mock code of the ${build_repo}."
                fi
                echo "[INFO] Successfully build and install the mock code of the ${build_repo}."

                #######################################################################
                # Display the contents of the installed package
                #######################################################################
                echo "[INFO] Start display the contents of the ${build_repo} hal mock package. "
                build_install_pkg_info="${log_file_prefix}_mock_pkg.log"
                local package_name=$(find ${build_path} -name "*_amd64.deb" -exec basename {} \; | sed -n '1p')
                # echo ${package_name}
                if [[ ${package_name} != "" ]];then
                    echo "$ dpkg -c ${package_name}" > ${build_install_pkg_info}
                    docker exec -it ${hal_docker_name} bash -c "cd /home/user/work/${build_path#*./} ; \
                                                            dpkg -c ${package_name} ; \
                                                            rm -fr /home/user/work/${build_path#*./}/* ;\
                                                            exit" >> ${build_install_pkg_info} 2>&1
                    if [[ $?  -ne 0 ]]; then
                        echo "[ERR ] Failed to display the contents of the ${build_repo} hal mock package."
                        abnormal_exit
                    fi
                    echo "[INFO] Successfully display the contents of the ${build_repo} hal mock package."
                else
                    docker exec -it ${hal_docker_name} bash -c "rm -fr /home/user/work/${build_path#*./}/* "
                    echo "[WARN] The hal mock package does not exist."
                fi
            fi

            #######################################################################
            # build and install souce code
            #######################################################################
            echo "[INFO] Start build and install the source code of the ${build_repo}."
            build_install_log="${log_file_prefix}_build.log"
            : > ${build_install_log}
            echo "-----------------------------------------------------"        >> ${build_install_log}
            echo "Start build and install the mock code of the ${build_repo}."  >> ${build_install_log}
            echo "-----------------------------------------------------"        >> ${build_install_log}
            docker run --rm -it -v ~:/home/hosthome:ro -v $(pwd):/workdir --name poky-$(id -un)-arene_integ --workdir=/workdir ${BUILD_DOCKER_REPOSITORY}:${BUILD_DOCKER_TAG} \
                bash -c "source /workdir/${build_sdk#*./} ;\
                        cd /workdir/${build_path#*./} ;\
                        echo '$ cmake ${BUILD_OPTION} .. ' ;\
                        cmake ${BUILD_OPTION} .. ;\
                        echo '$ make -j ${cpu_num}' ;\
                        make -j ${cpu_num} 2>&1 | tee ; \
                        sleep 1; echo;echo '$ make install DESTDIR=/workdir/${build_install_path#*./}' ;\
                        make install DESTDIR=/workdir/${build_install_path#*./}  2>&1 | tee ; \
                        mv /workdir/${build_install_path#*./}/${build_install_path_tmp}/* /workdir/${build_install_path#*./} ;\
                        rmdir -p /workdir/${build_install_path#*./}/${build_install_path_tmp} ;\
                        sleep 1; echo;echo '$ make package' ;\
                        make package  2>&1 | tee ; \
                        chown -R 1002:1002 * ; \
                        exit 0" >> ${build_install_log}  2>&1

            if [[ $(grep -Eo "make: \*\*\* [Makefile:[0-9]+: all] Error [0-9]+" ${build_install_log}) != "" ]]; then
                echo "[WARN] Failed to build and install the mock code of the ${build_repo}."
            fi
            echo "[INFO] Successfully build and install the mock code of the ${build_repo}."

            #######################################################################
            # Copy program to runtime container.
            #######################################################################
            echo "[INFO] Start copy ${build_repo} program to runtime container."
            echo ""                                                        >> ${build_install_log}
            echo "-----------------------------------------------------"   >> ${build_install_log}
            echo "Start copy ${build_repo} program to runtime container." >> ${build_install_log}
            echo "-----------------------------------------------------"   >> ${build_install_log}
            docker exec -it ${runtime_docker_name} bash -c "\
                        cp -arpf /home/root/share/${build_install_path#*./}/* / ;\
                        systemctl daemon-reload; \
                        exit 0" >> ${build_install_log}  2>&1

            if [[ $?  -ne 0 ]]; then
                echo "[ERR ] Failed to copy ${build_repo} program to runtime container."
                echo "Failed copy ${build_repo} program to runtime container." >> ${build_install_log}
                abnormal_exit
            fi
            echo "Successfully copy ${build_repo} program to runtime container." >> ${build_install_log}
            echo "[INFO] Successfully copy ${build_repo} program to runtime container."

            #######################################################################
            # Display the contents of the installed package
            #######################################################################
            echo "[INFO] Start display the contents of the ${build_repo} package. "
            build_install_pkg_info="${log_file_prefix}_pkg.log"
            package_name=$(find ${build_path} -name "*_core2-64.deb" -exec basename {} \; | sed -n '1p')
            # echo ${package_name}
            if [[ ${package_name} != "" ]];then
                echo "$ dpkg -c ${package_name}" > ${build_install_pkg_info}
                docker exec -it ${hal_docker_name} bash -c "cd /home/user/work/${build_path#*./} ; \
                                                dpkg -c ${package_name} ; \
                                                rm -fr /home/user/work/${build_path#*./} ;\
                                                exit 0" >> ${build_install_pkg_info} 2>&1
                if [[ $?  -ne 0 ]]; then
                    echo "[ERR ] Failed to display the contents of the ${build_repo} package."
                    abnormal_exit
                fi
                echo "[INFO] Successfully display the contents of the ${build_repo} package."

                sed -ri "s@${build_install_path_tmp}/opt@/opt@g" ${build_install_pkg_info}
                if [[ $?  -ne 0 ]]; then
                    echo "[ERR ] Failed to sed ${build_install_pkg_info}."
                    abnormal_exit
                fi
                sed -ri '/workdir/d' ${build_install_pkg_info}
                if [[ $?  -ne 0 ]]; then
                    echo "[ERR ] Failed to sed delete /workdir."
                    abnormal_exit
                fi
            else
                docker exec -it ${hal_docker_name} bash -c "rm -fr /home/user/work/${build_path#*./} "
                echo "[WARN] The runtime package does not exist."
            fi 
        else
            echo "[INFO] Build and install the mock code of the ${build_repo}."
            #make_build_install ${build_path} ${build_install_path} ${log_file_prefix}
            # TODO
            echo "[ERR ] Makefile is not supported at this time."
            abnormal_exit
            echo "[INFO] Build and install the source code of the ${build_repo}."
            #make_build_install_mock ${build_path} ${build_install_path} ${log_file_prefix}
            # TODO
        fi

        # save install info to file
        echo "Installed source code info:"                                                                  >> ${src_cfg_file}
        echo "    Repo Name: ${build_repo}"                                                                 >> ${src_cfg_file}
        echo "    Repo Branch: $(get_git_branch ${SRC_PATH}/${build_repo})"                                 >> ${src_cfg_file}
        echo "    Repo Version: $(get_git_version ${SRC_PATH}/${build_repo})"                               >> ${src_cfg_file}
        echo "------------------------------------------------------"                                       >> ${src_cfg_file}
        echo ""                                                                                             >> ${src_cfg_file}

        echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ${build_repo}"
        echo ""
    done
    echo "[INFO] Successfully build and install source code to test docker."
    echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
    echo ""
}

######################################################
# Execute test in the docker.
######################################################
function exec_test
{
    local test_unit_name=$1
    local env_cfg_file=${ENV_PATH}/${ENV_CFG_FILE#*./}
    local runtime_docker_name=$(sed -n '6p' ${env_cfg_file} | cut -d : -f 2)
    local hal_docker_name=$(sed -n '9p' ${env_cfg_file} | cut -d : -f 2)

    echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
    if [[ "all" == ${test_unit_name} ]]; then
        echo "[INFO] Start execute the tests for all the units in the repo."
        for test_unit_name in ${!TEST_TARGET[@]} ; do
            local test_unit_info=${TEST_TARGET[${test_unit_name}]}
            local service_file=$(echo ${test_unit_info} | cut -d : -f 1)
            local test_command=$(echo ${test_unit_info} | cut -d : -f 2)
            local test_log="${log_dir}/${test_unit_name}_test_result.log"

            echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ${test_unit_name}"
            #################################################################################
            # delete invalid contents
            #################################################################################
            # delete dlt log
            echo "[INFO] Start delete dlt log for unit ${test_unit_name}."
            docker exec -it ${runtime_docker_name} bash -c "rm -fr /var/volatile/log/dlt/*; exit"
            if [[ $? -ne 0 ]]; then
                echo "[ERR ] Failed to delete dlt log for unit ${test_unit_name}."
                abnormal_exit
            fi                            
            echo "[INFO] Successfully delete dlt log for unit ${test_unit_name}."

            # delete hal common test log
            echo "[INFO] Start delete hal common test log for unit ${test_unit_name}."
            docker exec -it ${hal_docker_name} bash -c "rm -fr /usr/local/bin/nohup.out; exit"
            if [[ $? -ne 0 ]]; then
                echo "[ERR ] Failed to delete hal common test log for unit ${test_unit_name}."
                abnormal_exit
            fi                            
            echo "[INFO] Successfully delete hal common test log for unit ${test_unit_name}."

            # delete backup data file
            local backup_file_for_unit=${BACKUP_FILE[${test_unit_name}]}
            if [[ -n ${backup_file_for_unit} ]]; then
                local backup_service_file=$(echo ${backup_file_for_unit} | cut -d : -f 1)
                local backup_file_path=$(echo ${backup_file_for_unit} | cut -d : -f 2)
                local backup_action=$(echo ${backup_file_for_unit} | cut -d : -f 3)
                if [[ ${backup_action} == "delete" ]]; then 
                    echo "[INFO] Start delete backup data file for unit ${test_unit_name}."
                    docker exec -it ${runtime_docker_name} bash -c "
                        systemctl stop ${backup_service_file}; \
                        rm -fr ${backup_file_path}; \
                        systemctl start ${backup_service_file}; \
                        exit"
                    if [[ $? -ne 0 ]]; then
                        echo "[ERR ] Failed to delete backup data file for unit ${test_unit_name}."
                        abnormal_exit
                    fi                            
                    echo "[INFO] Successfully delete backup data file for unit ${test_unit_name}." 
                fi
            fi
            #################################################################################
            # restart docker container
            #################################################################################
            restart_test_docker_container

            #################################################################################
            # start service
            #################################################################################
            local service_status=$(docker exec -it ${runtime_docker_name} bash -c "systemctl is-active  ${service_file} | tr -d '\n' " 2>&1)
            if [[ ${service_status} != "active" ]]; then
                echo "[WARR] The ${test_unit_name} service is not started!"
                echo "[INFO] Restart ${test_unit_name} service ...     "
                docker exec -it ${runtime_docker_name}  bash -c "systemctl restart ${service_file}" 2>&1
                if [[ $?  -ne 0 ]]; then
                    echo "[ERR ] Failed to restart ${test_unit_name} service."
                    abnormal_exit
                fi
                echo "[INFO] Successfully restart ${test_unit_name} service."
            fi

            #################################################################################
            # start execute test
            #################################################################################
            echo "[INFO] Start execute the test for unit ${test_unit_name}."
            echo "$ ${test_command}" > ${test_log}
            docker exec -it ${runtime_docker_name} bash -c "${test_command} 2>&1 | tee ;\
                                                    exit" >> ${test_log} 2>&1
            if [[ $?  -ne 0 ]]; then
                echo "Failed to execute the test for unit ${test_unit_name}."  >> ${test_log}
                echo "[ERR ] Failed to execute the test for unit ${test_unit_name}."
                abnormal_exit
            fi
            echo "Successfully execute the test for unit ${test_unit_name}."   >> ${test_log}
            echo "[INFO] Successfully execute the test for unit ${test_unit_name}."

            #################################################################################
            # copy test result from runtime docker
            #################################################################################
            echo "[INFO] Start copy the test result for unit ${test_unit_name}."
            docker exec -it ${runtime_docker_name} bash -c "mkdir -p /home/root/share/${log_dir#${WORK_PATH}/}/${test_unit_name}/dlt ; \
                                                    cp -rf /tmp/${test_unit_name}_* /home/root/share/${log_dir#${WORK_PATH}/}/${test_unit_name}/ ;\
                                                    cp -rf /var/volatile/log/dlt/* /home/root/share/${log_dir#${WORK_PATH}/}/${test_unit_name}/dlt/ ;\
                                                    chown -R 1002:1002 /home/root/share/${log_dir#${WORK_PATH}/}/* ;\
                                                    exit"
            if [[ $? -ne 0 ]]; then
                echo "[ERR ] Failed to copy the test result for unit ${test_unit_name}."
                abnormal_exit
            fi                            
            echo "[INFO] Successfully copy the test result for unit ${test_unit_name}."

            #################################################################################
            # copy hal common log from hal docker
            #################################################################################
            echo "[INFO] Start copy the hal common test log for unit ${test_unit_name}."
            docker exec -it ${hal_docker_name} bash -c "cp -rf /usr/local/bin/nohup.out /home/user/work/${log_dir#${WORK_PATH}/}/${test_unit_name}/ ;\
                                                    chown -R 1002:1002 /home/user/work/${log_dir#${WORK_PATH}/}/${test_unit_name}/* ;\
                                                    exit"
            if [[ $? -ne 0 ]]; then
                echo "[ERR ] Failed to copy the hal common test log for unit ${test_unit_name}."
                abnormal_exit
            fi                            
            echo "[INFO] Successfully copy the hal common test log for unit ${test_unit_name}."

            #################################################################################
            echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ${test_unit_name}"
            echo ""
        done
        echo "[INFO] Successfully execute the tests for all the units in the repo."
    else
        local test_unit_info=${TEST_TARGET[${test_unit_name}]}
        local service_file=$(echo ${test_unit_info} | cut -d : -f 1)
        local test_command=$(echo ${test_unit_info} | cut -d : -f 2)
        local test_log="${log_dir}/${test_unit_name}_test_result.log"
        #################################################################################
        # delete invalid contents
        #################################################################################
        # delete dlt log
        echo "[INFO] Start delete dlt log for unit ${test_unit_name}."
        docker exec -it ${runtime_docker_name} bash -c "rm -fr /var/volatile/log/dlt/*; exit"
        if [[ $? -ne 0 ]]; then
            echo "[ERR ] Failed to delete dlt log for unit ${test_unit_name}."
            abnormal_exit
        fi                            
        echo "[INFO] Successfully delete dlt log for unit ${test_unit_name}."

        # delete hal common test log
        echo "[INFO] Start delete hal common test log for unit ${test_unit_name}."
        docker exec -it ${hal_docker_name} bash -c "rm -fr /usr/local/bin/nohup.out; exit"
        if [[ $? -ne 0 ]]; then
            echo "[ERR ] Failed to delete hal common test log for unit ${test_unit_name}."
            abnormal_exit
        fi                            
        echo "[INFO] Successfully delete hal common test log for unit ${test_unit_name}."

        # delete backup data file
        local backup_file_for_unit=${BACKUP_FILE[${test_unit_name}]}
        if [[ -n ${backup_file_for_unit} ]]; then
            local backup_service_file=$(echo ${backup_file_for_unit} | cut -d : -f 1)
            local backup_file_path=$(echo ${backup_file_for_unit} | cut -d : -f 2)
            local backup_action=$(echo ${backup_file_for_unit} | cut -d : -f 3)
            if [[ ${backup_action} == "delete" ]]; then 
                echo "[INFO] Start delete backup data file for unit ${test_unit_name}."
                docker exec -it ${runtime_docker_name} bash -c "
                    systemctl stop ${backup_service_file}; \
                    rm -fr ${backup_file_path}; \
                    systemctl start ${backup_service_file}; \
                    exit"
                if [[ $? -ne 0 ]]; then
                    echo "[ERR ] Failed to delete backup data file for unit ${test_unit_name}."
                    abnormal_exit
                fi                            
                echo "[INFO] Successfully delete backup data file for unit ${test_unit_name}." 
            fi
        fi
        #################################################################################
        # restart docker container
        #################################################################################
        restart_test_docker_container

        #################################################################################
        # start service
        #################################################################################
        local service_status=$(docker exec -it ${runtime_docker_name} bash -c "systemctl is-active  ${service_file} | tr -d '\n' " 2>&1)
        if [[ ${service_status} != "active" ]]; then
            echo "[WARR] The ${test_unit_name} service is not started!"
            echo "[INFO] Restart ${test_unit_name} service ...     "
            docker exec -it ${runtime_docker_name}  bash -c "systemctl restart ${service_file}" 2>&1
            if [[ $?  -ne 0 ]]; then
                echo "[ERR ] Failed to restart ${test_unit_name} service."
                abnormal_exit
            fi
            echo "[INFO] Successfully restart ${test_unit_name} service."
        fi

        #################################################################################
        # start execute test
        #################################################################################
        echo "[INFO] Start execute the test for unit ${test_unit_name}."
        echo "$ ${test_command}" > ${test_log}
        docker exec -it ${runtime_docker_name} bash -c "${test_command} 2>&1 | tee ;\
                                                exit" >> ${test_log} 2>&1
        if [[ $?  -ne 0 ]]; then
            echo "Failed to execute the test for unit ${test_unit_name}."  >> ${test_log}
            echo "[ERR ] Failed to execute the test for unit ${test_unit_name}."
            abnormal_exit
        fi
        echo "Successfully execute the test for unit ${test_unit_name}."   >> ${test_log}
        echo "[INFO] Successfully execute the test for unit ${test_unit_name}."

        #################################################################################
        # copy test result from runtime docker
        #################################################################################
        echo "[INFO] Start copy the test result for unit ${test_unit_name}."
        docker exec -it ${runtime_docker_name} bash -c "cp -rf /tmp/${test_unit_name}_* /home/root/share/${log_dir#${WORK_PATH}/}/ ;\
                                                mkdir -p /home/root/share/${log_dir#${WORK_PATH}/}/dlt ;\
                                                cp -rf /var/volatile/log/dlt/* /home/root/share/${log_dir#${WORK_PATH}/}/dlt/ ;\
                                                chown -R 1002:1002 /home/root/share/${log_dir#${WORK_PATH}/}/* ;\
                                                exit"
        echo "[INFO] Successfully copy the test result for unit ${test_unit_name}."
        
        #################################################################################
        # copy hal common log from hal docker
        #################################################################################
        sleep 5
        echo "[INFO] Start copy the hal common test log for unit ${test_unit_name}."
        docker exec -it ${hal_docker_name} bash -c "cp -rf /usr/local/bin/nohup.out /home/user/work/${log_dir#${WORK_PATH}/}/ ;\
                                                chown -R 1002:1002 /home/user/work/${log_dir#${WORK_PATH}/}/* ;\
                                                exit"
        if [[ $? -ne 0 ]]; then
            echo "[ERR ] Failed to copy the hal common test log for unit ${test_unit_name}."
            abnormal_exit
        fi                            
        echo "[INFO] Successfully copy the hal common test log for unit ${test_unit_name}."
    fi

    echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
}

######################################################
# main
######################################################
if [[ $# -lt 1 ]] || [[ $# -gt 2 ]]; then
    echo "line:${LINENO} [ERR]=> Incorrect number of parameters! count=$#" 1>&2
    usage
    exit 1
else
    case ${1} in
        "help")
            usage
            ;;
        "show-env")
            show_env_info
            ;;
        "init-env")
            start_run
            # init build and test environment.
            init_build_and_test_env            >> ${log} 2>&1
            normal_exit
            ;;
        "update")
            start_run
            # update source code from git
            update_source_code                 >> ${log} 2>&1
            normal_exit
            ;;
        "update-sdk")
            start_run
            # update source code from git
            build_source_code_to_sdk                 >> ${log} 2>&1
            normal_exit
            ;;
        "build")
            start_run
            # out env info
            output_current_env_info             >> ${log} 2>&1
            # build and install
            build_install_source_code           >> ${log} 2>&1
            # out source info
            output_current_source_info          >> ${log} 2>&1
            # restart docker container
            # restart_test_docker_container       >> ${log} 2>&1
            normal_exit
            ;;
        "test")
            start_run
            # out env info
            output_current_env_info             >> ${log} 2>&1
            # out source info
            #output_current_source_info          >> ${log} 2>&1
            if [[ "${2}" != "" ]] && ( [[ "${2}" == "all" ]] || [[ "${TEST_TARGET[${2}]}" != "" ]]); then
                exec_test ${2}                  >> ${log} 2>&1
            else
                echo "line:${LINENO} [ERR]=> Parameter unit is incorrect! unit=${2}" 1>&2
                exit 1
            fi
            normal_exit
            ;;
        "build-test")
            if [[ "${2}" != "" ]] && ( [[ "${2}" == "all" ]] || [[ "${TEST_TARGET[${2}]}" != "" ]]); then
                start_run
                # out env info
                output_current_env_info             >> ${log} 2>&1
                # build and install
                build_install_source_code           >> ${log} 2>&1
                # out source info
                output_current_source_info          >> ${log} 2>&1
                # restart docker container
                # restart_test_docker_container       >> ${log} 2>&1
                # test
                exec_test ${2}                      >> ${log} 2>&1
                normal_exit
            else
                echo "line:${LINENO} [ERR]=> Parameter unit is incorrect! unit=${2}" 1>&2
                exit 1
            fi
            ;;
        "reset-docker")
            start_run
            # reset test docker container
            stop_test_docker_container           >> ${log} 2>&1
            # restart test docker container
            restart_test_docker_container          >> ${log} 2>&1
            normal_exit
            ;;
        "restart-docker")
            start_run
            # restart test docker container
            restart_test_docker_container         >> ${log} 2>&1
            normal_exit
            ;;
        "delete")
            start_run
            #Delete invalid source code from local.
            delete_invalid_source                  >> ${log} 2>&1
            normal_exit
            ;;
        "delete-log")
            start_run
            #Delete old logs from local.
            delete_old_log                        >> ${log} 2>&1
            normal_exit
            ;;
        *)
            echo "line:${LINENO} [ERR]=> Parameter command is incorrect! command=${1}" 1>&2
            usage
            exit 1
            ;;
    esac
fi